#include "mainwindow.h"
#include <QTransform>
#include <QPixmap>
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , pix(500, 500)
{
    ui->setupUi(this);
    this->resize(1700, 1000);
    this->move(130,130);

    this->QPictureSave();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    static_cast<void>(event);
    //this->painterBasicTest();
    //this->QPenTest();
    //this->QPixmapTest();
    //this->QPainterSaveTest();

    //QPainter painter(this);
    //this->QPixmapCharacter();
    //painter.drawPixmap(0, 0, pix);

    //this->QImage();
    this->QPictureLoad();
}

void MainWindow::painterBasicTest()
{
    //当 paintEvent 被调用时，Qt 设置了一个绘画环境专用于当前控件（本例中为 MainWindow）。
    //尝试在 MainWindow 的 paintEvent 中使用 QPainter 在 ui->centralwidget 上绘图，违反了 Qt 的绘图模型
    //因为 paintEvent 应专注于处理发送给它的控件（this 指向的对象）的绘图。

    //在 Qt 中，控件的绘画是基于层级的。当你尝试在 MainWindow 的 paintEvent 中绘制 ui->centralwidget
    //你实际上是试图操纵另一个控件的绘画行为，这通常不是推荐的做法。每个控件（QWidget）应负责其自身的绘画，并且通常通过其自己的 paintEvent 实现。

    //如果你需要自定义 ui->centralwidget 的绘图行为，应该通过子类化 QWidget 并重写它的 paintEvent 方法。
    //这样，你可以在那里安全地设置 QPainter 并执行绘图操作，而无需担心违反 Qt 的绘图规则。
    //QPainter painter(ui->centralwidget);

    //实例化画家对象 this表示的是在当前窗口中绘画,即绘画设备
    QPainter painter(this);

    //画一条线
    painter.drawLine(QPoint(50, 50), QPoint(50, 500));

    //再画一条线
    painter.drawLine(QPoint(50, 50), QPoint(500, 50));

    //再画一条线
    painter.drawLine(QPoint(50, 500), QPoint(500, 500));

    //再画一条线
    painter.drawLine(QPoint(500, 50), QPoint(500, 500));

    //再画一条线
    painter.drawLine(QPoint(50, 50), QPoint(500, 500));

    //绘制一个矩形
    painter.drawRect(50, 50, 300, 300);

    //绘制一个正圆形
    painter.drawEllipse(QPoint(700, 200), 100, 100);

    //绘制两个椭圆
    painter.drawEllipse(QPoint(700, 200), 100, 50);
    painter.drawEllipse(QPoint(700, 200), 50, 100);

    //绘制文字
    //设置字体
    QFont font("华文行楷", 50);
    painter.setFont(font);
    //设置画笔颜色
    painter.setPen(Qt::red);
    //画文字
    //注意理解这里的坐标的位置此处的0横坐标，
    //表示的是文字最左侧的位置此处的100纵坐标，表示的是文字的“基线位置”
    //如果文字在基线之上,那么应该显示不出来,比如设置0,0
    painter.drawText(800, 800, "坤兄,yyds!!!");

}

void MainWindow::QPenTest()
{
//QPainter 在绘制时，是有一个默认的画笔的。在使用时也可以自定义画笔。
//在 Qt 中，QPen类中定义了 QPainter 应该如何绘制形状、线条和轮廓。同时通过 QPen类 可以设置画笔的线宽、颜色、样式、画刷等。
//画笔的颜色可以在实例化画笔对象时进行设置，画笔的宽度是通过 setWidth() 方法进行设置
//画笔的风格是通过setStyle(）方法进行设置，设置画刷主要是通过 setBrush() 方法。

    //实例化画家对象
    QPainter painter(this);

    //设置画笔
    QPen pen(QColor(0, 0, 255));

    //设置画笔风格
    pen.setStyle(Qt::DashLine);

    //设置画笔宽度
    pen.setWidth(5);

    //在 Qt 中，画刷是使用 QBrush类 来描述，画刷大多用于填充。QBrush定义了QPainter的填充模式，具有样式、颜色、渐变以及纹理等属性。
    //画刷的格式中定义了填充的样式，使用 Qt::BrushStyle 枚举，默认值是 Qt::NoBrush，也就是不进行任何填充。
    //可以通过 Qt 助手查找画刷的格式。
    //设置画刷,给封闭图形填充颜色
    QBrush brush(QColor(0, 255, 0));
    //QBrush brush(Qt::cyan);

    //设置画刷风格
    brush.setStyle(Qt::CrossPattern);

    //让画家使用画笔
    painter.setPen(pen);

    //让画家使用画刷
    painter.setBrush(brush);

    //绘制圆
    painter.drawEllipse(QPoint(200, 200), 100, 100);
}

void MainWindow::QPixmapTest()
{
//Qt 提供了四个类来处理图像数据：QImage、QPixmap、QBitmap 和 QPicture，它们都是常用的图设备。
//其中QImage主要用来进行 I/O 处理，它对 I/O 处理操作进行了优化，而且可以用来直接访问和操作像素
//QPixmap 主要用来在屏幕上显示图像，它对在屏幕上显示图像进行了优化；
//QBitmap是 QPixmap 的子类，用来处理颜色深度为1的图像，即只能显示黑白两种颜色；
//QPicture 用来记录并重演 QPainter 命令

    QPainter painter(this);
    //调整 QPainter 的坐标系统，将原点移动到窗口的 (100, 100) 位置
    painter.translate(100, 100);

    QTransform transform;
    //scale() 方法用于设置变换矩阵的缩放比例。这里的参数 1, -1 指定了在 X 轴方向上保持不变，在 Y 轴方向上将图像翻转。
    //缩放因子 1 表示 X 轴的缩放为正常比例，不进行缩放。
    //缩放因子 -1 表示 Y 轴的图像将被翻转。这是因为任何 Y 值在变换后都将乘以 -1，导致图像在垂直方向上翻转。
    transform.scale(1, -1);
    painter.setTransform(transform, true);

    QPixmap pixmap(QPixmap(":/image/kun.jpg"));
    painter.drawPixmap(0, -pixmap.height(), pixmap);
    //painter.drawPixmap(0, 0, pixmap);

    painter.resetTransform();
    painter.translate(100, 100);
    //对图片进行缩放
    //以700,100点开始画图,图片尺寸变为50*100
    painter.drawPixmap(700, 100, 50, 100, QPixmap(":/image/kun.jpg"));
}

void MainWindow::QPainterSaveTest()
{
    //实例化画家对象
    QPainter painter(this);
    //画圆
    painter.drawRect(100, 100, 200, 300);
    //画家移动
    painter.translate(200, 200);
    //保存画家状态
    painter.save();
    //画圆
    painter.drawRect(100, 100, 200, 300);
    //画家移动
    painter.translate(200, 200);
    //还原画家到保存的状态
    painter.restore();
    //画圆,可以发现和第二圆是重合的,因为此时的画家状态就是save的状态
    painter.drawRect(100, 100, 200, 300);
}

//前面的代码中我们是使用 QWidget 作为绘图设备. 在 Qt 中还存在下列三个比较特殊的绘图设备.
//• QPixmap 用于在显示器上显示图片.
//• QImage 用于对图片进行像素级修改.
//• QPicture 用于对 QPainter 的一系列操作进行存档.

//使用 QPainter 直接在上面进行绘制图形
//• 通过文件路径加载并显示图片.
//• 搭配 QPainter 的 drawPixmap()函数, 可以把这个图片绘制到一个 QLabel、QPushButton 等控件上.
//• 和系统/显示设备强相关, 不同系统/显示设备下, QPixmap 的显示可能会有所差别.
void MainWindow::QPixmapCharacter()
{
    //设置QPixmap的背景透明
    pix.fill(Qt::transparent);
    QPainter painter(&pix);

    painter.setPen(Qt::red);

    painter.drawEllipse(QPoint(100, 100), 100, 100);
    pix.save(R"(G:\code\qt\QPainter\image\pix.png)");
}

//QImage 的核心特性:
//• 使用 QPainter 直接在上面进行绘制图形.
//• 通过文件路径加载并显示图片.
//• 能够针对图片进行像素级别的操作(操作某个指定的像素).
//• 独立于硬件的绘制系统, 能够在不同系统之上提供一致的显示.
void MainWindow::QImage()
{
    QPainter painter(this);

    class QImage img;
    img.load(":/image/kun.jpg");

    //修改像素点
    for (int i = 100; i < 200; ++i) {
        for (int j = 100; j < 200; ++j) {
            QRgb rgb = qRgb(0, 255, 0);
            img.setPixel(i, j, rgb);
        }
    }

    painter.drawImage(0, 0, img);

}

//QPicture 核心特性:
//• 使用 QPainter 直接在上面进行绘制图形.
//• 通过文件路径加载并显示图片.
//• 能够记录 QPainter 的操作步骤.
//• 独立于硬件的绘制系统, 能够在不同系统之上提供一致的显示.
//注意:
//QPicture 加载的必须是自身的存档文件, 而不能是任意的 png, jpg 等图片文件
void MainWindow::QPictureSave()
{
    QPicture pic;
    QPainter painter;
    painter.begin(&pic);
    //开始往pic绘图设备上绘画
    painter.setPen(QPen(Qt::red));
    painter.drawEllipse(QPoint(200, 200), 100, 100);
    //结束绘画
    painter.end();
    pic.save(R"(G:\code\qt\QPainter\image\pic.pic)");
}

void MainWindow::QPictureLoad()
{
    QPainter painter(this);

    //重现绘图指令
    QPicture pic;
    //加载图片
    pic.load(R"(G:\code\qt\QPainter\image\pic.pic)");
    painter.drawPicture(0, 0, pic);
}

